# -*- coding: utf-8 -*-
# @Author	: brotherbaby
# @Date		: 2023/11/2 9:37
# @Last Modified by:   brotherbaby
# @Last Modified time: 2023/11/2 9:37
# Thanks for your comments!

import datetime
import json
import logging
import time
import traceback

from flask import request

from src.consts import SysDictType
from src.db_proxy.connect import DbConnector
from src.db_proxy.models.order import Order
from src.db_proxy.models.shoes_detail import ShoesDetail
from src.db_proxy.models.site import Site
from src.db_proxy.models.sys_dict import SysDict
from src.tornadoweb_app import app
from .utils import verify_token

logger = logging.getLogger(__name__)


@app.route("/wechat_milangze/statistics/district_shoes_count", methods=["GET"])
def district_shoes_count_api():
    resp = {"code": 0, "message": "success"}
    try:
        params = request.args
        for f in ["client_type", "access_token"]:
            if not params.get(f):
                resp.update({"code": -1, "message": "lack %s" % f})
                return json.dumps(resp)
        if not verify_token(params.get("access_token"), params.get("client_type")):
            resp.update({"code": 403, "message": "invalid access_token, query new one and try again"})
            return json.dumps(resp)
        db_conn = DbConnector()
        session = db_conn.get_session()
        query_days = 7
        if params.get("query_days"):
            query_days = int(params["query_days"])
        commit_time_start_dt = datetime.date.today() - datetime.timedelta(days=query_days)
        commit_time_start_st = int(
            time.mktime(time.strptime(str(commit_time_start_dt) + ' 00:00:00', '%Y-%m-%d %H:%M:%S'))) * 1000
        commit_time_end_st = int(
            time.mktime(time.strptime(str(datetime.date.today()) + ' 00:00:00', '%Y-%m-%d %H:%M:%S'))) * 1000
        sds = session.query(Order.id, Site.district, ShoesDetail.id).filter(
            Order.commit_time.between(commit_time_start_st, commit_time_end_st),
            Order.obsoleted == False).join(Site).outerjoin(ShoesDetail, ShoesDetail.order_id == Order.id).all()
        districts = session.query(SysDict).filter(SysDict.type == SysDictType.District.value,
                                                  SysDict.obsoleted == False).all()
        stats = {i.value: 0 for i in districts}
        district_sort = {i.value: i.sort_value for i in districts}
        for sd in sds or []:
            if not sd[1]:
                continue
            if str(sd[1]) not in stats:
                stats[str(sd[1])] = 1
            else:
                stats[str(sd[1])] += 1
        resp_data = [{"district": k, "count": v, "sort_value": district_sort[k]} for k, v in stats.items()]
        resp_data.sort(key=lambda x: x["count"], reverse=True)
        resp["data"] = resp_data
    except Exception as e:
        logger.error(traceback.format_exc())
        resp.update({"code": -1, "message": str(e)})
    finally:
        if "session" in locals() and "db_conn" in locals():
            db_conn.close_session(session)
    return json.dumps(resp)


@app.route("/wechat_milangze/statistics/district_shoes_count_trend", methods=["GET"])
def district_shoes_count_trend_api():
    resp = {"code": 0, "message": "success"}
    try:
        params = request.args
        for f in ["client_type", "access_token"]:
            if not params.get(f):
                resp.update({"code": -1, "message": "lack %s" % f})
                return json.dumps(resp)
        if not verify_token(params.get("access_token"), params.get("client_type")):
            resp.update({"code": 403, "message": "invalid access_token, query new one and try again"})
            return json.dumps(resp)
        db_conn = DbConnector()
        session = db_conn.get_session()
        query_days = 7
        if params.get("query_days"):
            query_days = int(params["query_days"])
        commit_time_start_dt = datetime.date.today() - datetime.timedelta(days=query_days)
        commit_time_start_st = int(
            time.mktime(time.strptime(str(commit_time_start_dt) + ' 00:00:00', '%Y-%m-%d %H:%M:%S'))) * 1000
        commit_time_end_st = int(
            time.mktime(time.strptime(str(datetime.date.today()) + ' 00:00:00', '%Y-%m-%d %H:%M:%S'))) * 1000
        q = [
            Order.commit_time.between(commit_time_start_st, commit_time_end_st),
            Order.obsoleted == False
        ]
        if params.get("district"):
            q.append(Site.district == params.get("district"))
        sql = f"select milangze_site.district, \
            DATE_FORMAT(DATE(FROM_UNIXTIME(milangze_order.commit_time/1000)), '%Y-%m-%d'), \
            count(milangze_shoesdetail.id) from milangze_order \
            left join milangze_site on milangze_order.site_no=milangze_site.no \
            left join milangze_shoesdetail on milangze_order.id=milangze_shoesdetail.order_id \
            where milangze_order.obsoleted = 0 and \
            milangze_order.commit_time between {commit_time_start_st} and {commit_time_end_st} "
        if params.get("district"):
            sql += f"milangze_site.district = {params.get('district')}"
        sds = session.execute(sql + "group by milangze_site.district, \
            DATE_FORMAT(DATE(FROM_UNIXTIME(milangze_order.commit_time/1000)), '%Y-%m-%d')")
        # ords = session.query(Site.district, datetime.datetime.fromtimestamp(int(Order.commit_time) / 1000).strftime(
        #     "%Y-%m-%d"), func.count(Order.id)).filter(*q).join(Site).group_by(
        #     Site.district, datetime.datetime.fromtimestamp(int(Order.commit_time) / 1000).strftime("%Y-%m-%d"))
        districts = session.query(SysDict).filter(SysDict.type == SysDictType.District.value,
                                                  SysDict.obsoleted == False).all()
        days_str = [(commit_time_start_dt + datetime.timedelta(days=x)).strftime("%Y-%m-%d") for x in range((datetime.date.today()-commit_time_start_dt).days)]
        stats = {i.value: {j: 0 for j in days_str} for i in districts}
        district_sort = {i.value: i.sort_value for i in districts}
        for sd in sds or []:
            if str(sd[0]) not in stats:
                stats[str(sd[0])] = {
                    str(sd[1]): int(sd[2])
                }
            else:
                if str(sd[1]) in stats[str(sd[0])]:
                    stats[str(sd[0])][str(sd[1])] += int(sd[2])
                else:
                    stats[str(sd[0])][str(sd[1])] = int(sd[2])
        res_data = {}
        for k, v in stats.items():
            res_data[k] = [list(v.keys()), list(v.values()), district_sort[k]]
        resp["data"] = res_data
    except Exception as e:
        logger.error(traceback.format_exc())
        resp.update({"code": -1, "message": str(e)})
    finally:
        if "session" in locals() and "db_conn" in locals():
            db_conn.close_session(session)
    return json.dumps(resp)
